<?php
/**
 * 字符串处理
 *
 **/
class FendString
{
    /**
     * 过滤掉标签
     * @param      string 源串
     * @param null $tags
     *
     * @return string
     */
    public static function filterContent($text, $tags = null)
    {
        $text = htmlentities($text, ENT_NOQUOTES, 'UTF-8');
        return $text;
    }
    /**
     * 博客内容格式化
     *
     * @param string $text
     * @param int $uid 用户ID
     * @param bool $show_em
     * @return string
     */
    public static function formatText($text, $uid = 0, $show_em = true)
    {
        if (empty($text)) {
            return false;
        }

        $newText = '';

        $mc = preg_split(";(#[^#\s]{1,60}#|%[^%][\x{4e00}-\x{9fa5}a-zA-Z0-9]{1,30}%|[a-z0-9\-_]*[a-z0-9]@(?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+|@[\x{4e00}-\x{9fa5}0-9A-Za-z_\-]{1,30}|http://(?:www\.)?(?:[a-zA-Z0-9][a-zA-Z0-9\-]*\.)?[a-zA-Z0-9][a-zA-Z0-9\-]*(?:\.[-_A-Z0-9a-z\$\.\+\!\*\/\,\:\;\@\&\=\?\~\#\%]+)+|<a\s+href=[\"'][^\"']+[\"'][^>]*>.+?</a>);sium", $text, -1, PREG_SPLIT_DELIM_CAPTURE);
        foreach ($mc as $i => $v) {
            if ($i % 2 == 1) {
                $tmp_str = substr($v, 1, -1);
                $strlen  = mb_strwidth(trim($tmp_str), 'utf8');
                if (substr($v, 0, 1) . substr($v, -1, 1) == '##') {
                    $newText .= '<a href="' . 'nt/' . urlencode($tmp_str) . '">' . $v . '</a>';
                } elseif (substr($v, 0, 1) . substr($v, -1, 1) == '%%' && 0 < $strlen && $strlen <= 60 && preg_match("/^([\x{4e00}-\x{9fa5}]|[a-zA-Z0-9])+$/u", $tmp_str)) {
                    $newText .= '<a href="' . 'ns/' . urlencode($tmp_str) . '">' . $v . '</a>';
                } elseif (substr($v, 0, 1) == '@' && 0 < $strlen && $strlen <= 20) {
                    $newText .= '<a href="'  . 'n/' . urlencode(substr($v, 1)) . '" data-usercard="true" data-uname="' . substr($v, 1) . '">' . $v . '</a>';
                } elseif (preg_match("/((?:https?|ftp):\/\/(?:www\.)?(?:[a-zA-Z0-9][a-zA-Z0-9\-]*\.)?[a-zA-Z0-9][a-zA-Z0-9\-]*(?:\.[-_A-Z0-9a-z\$\.\+\!\*\/,:;@&=\?\~\#\%]+)+)/u", $v)) {
                    // 短链替换
                    $newText .= '<a title="' . $v . '" href="' . $v . '" target="_blank">' . $v . '</a>';
                } else {
                    $newText .= $v;
                }
            } else {
                $newText .= $v;
            }
        }
        $newText = preg_replace('/\r?\n/', '<br>', $newText);
        $text    = preg_replace('/(\<br\>\s*)/i', '<p>', $newText);
        return $text;
    }

    /**
     * 获取讨论内容中的At用户名
     *
     * @param  string $content
     * @return array
     */
    public static function getAt($content)
    {
        if (empty($content)) {
            return array();
        }
        $atAry = array();
        $mc    = preg_split(";(#[^#]+#|[a-z0-9\-_]*[a-z0-9]@(?:[a-z0-9-]+)(?:\.[a-z0-9-]+)+|@[\x{4e00}-\x{9fa5}0-9A-Za-z_\-]+|http://(?:sinaurl|t)\.cn/[a-z0-9]+|<a\s+href=[\"'][^\"']+[\"'][^>]*>.+?</a>);sium", $content, -1, PREG_SPLIT_DELIM_CAPTURE);
        foreach ($mc as $i => $v) {
            if ($i % 2 == 1) {
                if (substr($v, 0, 1) == '@') {
                    $atAry[$v] = substr($v, 1);
                }
            }
        }
        return $atAry;
    }

    /**
     * 裁剪替换
     *
     * @param string $str 源串
     * @param int $len
     * @param string $ext 需要替换的
     * @return string
     */
    public static function getShort($str, $len = 40, $ext = '...')
    {

        $str = preg_replace("/(\s+)/", ' ', $str);
        $str = preg_replace("/\[i\](.+?)\[\/i\]/is", "\\1", $str);
        $str = preg_replace("/\[u\](.+?)\[\/u\]/is", "\\1", $str);
        $str = preg_replace("/\[b\](.+?)\[\/b\]/is", "\\1", $str);
        $str = preg_replace('/(\[br\]\s*){1,}/is', '', $str);
        $str = preg_replace("/\[img\](.+?)\[\/img\]/is", "", $str);

        $source_str = html_entity_decode($str, ENT_COMPAT, 'UTF-8');
        if (strlen($source_str) <= $len) {
            return $str;
        }
        preg_match_all('/((?:https?|ftp):\/\/(?:www\.)?(?:[a-zA-Z0-9][a-zA-Z0-9\-]*\.)?[a-zA-Z0-9][a-zA-Z0-9\-]*(?:\.[-_A-Z0-9a-z\$\.\+\!\*\/,:;@&=\?\~\#\%]+)+(?:\:[-_A-Z0-9a-z\$\.\+\!\*\/,:;@&=\?\~\#\%]*)?(?:\/[^\x{4e00}-\x{9fa5}\s<\'\"“”‘’]*)?)/u', $str, $match_url);
        preg_match_all(';(@[\x{4e00}-\x{9fa5}0-9A-Za-z_\-]+);sium', $str, $match_uname);

        if (!empty($match_url)) {
            foreach ($match_url[0] as $key => $v) {
                $pos  = strpos($str, $v);
                $slen = strlen($v);
                if ($pos < $len && ($pos + $slen) > $len) {
                    return substr($str, 0, $pos + $slen) . $ext;
                    break;
                }
            }
        }
        if (!empty($match_uname)) {
            foreach ($match_uname[0] as $key => $v) {
                $pos  = strpos($str, $v);
                $slen = strlen($v);
                if ($pos < $len && ($pos + $slen) > $len) {
                    return substr($str, 0, $pos + $slen) . $ext;
                    break;
                }
            }
        }
        // 截取
        $i    = 0;
        $tlen = 0;
        $tstr = '';
        while ($tlen < $len) {
            $chr    = mb_substr($source_str, $i, 1, 'utf8');
            $chrLen = ord($chr) > 127 ? 3 : 1;

            if ($tlen + $chrLen > $len)
                break;

            $tstr .= $chr;
            $tlen += $chrLen;
            $i++;
        }

        if ($tstr != $source_str) {
            //表情补全处理
            $rs  = mb_substr($tstr, -6, 8, 'utf8');
            $pos = strpos($rs, "[em");
            if (!empty($pos)) {
                $cut_str = substr($source_str, $len);
                !empty($cut_str) && $end_pos = strpos($cut_str, ']');
                !empty($end_pos) && $end_pos <= 5 && $pos_str = substr($cut_str, 0, $end_pos);
                !empty($pos_str) && $tstr    .= $pos_str . ']';
            }
            $tstr .= $ext;
        }
        $tstr = FendString::filterContent($tstr);
        return $tstr;
    }

    /**
     * 追加URL参数
     * 检测是?&追加
     *
     * @param  string $str  url地址
     * @param  string $pars 需要追加的参数
     * @return string
     * */
    public static function subUrl($str, $pars)
    {
        if (false === strpos($str, '?')) {
            $str .= '?';
        } else {
            $str .= '&';
        }
        $str .= $pars;

        return $str;
    }

    /**
     * @param      $idStr id串  1,2,3,4
     * @param      $id        要加入的id
     * @param bool $reverse  加载的位置
     *
     * @return string
     */
    public static function addIdToIdStr($idStr, $id, $reverse = false)
    {
        if ($reverse) {
            return $idStr ? $idStr . ',' . $id : $id;
        }
        return $idStr ? $id . ',' . $idStr : $id;
    }

    /**
     * 移除串中ID
     * @param $idStr
     * @param $id
     *
     * @return string
     */
    public static function removeIdFromIdStr($idStr, $id)
    {
        $idStr = ',' . $idStr . ',';
        return trim(str_replace(",{$id},", ',', $idStr), ',');
    }

    /**
     * 判断ID是否在串中
     * @param $idStr
     * @param $id
     *
     * @return bool
     */
    public static function isExistInIdStr($idStr, $id)
    {
        $idStr = ',' . $idStr . ',';
        return (strpos($idStr, ",{$id},") !== false);
    }

    /**
     * 处理ID串为半角","分隔
     * @param $id_str
     *
     * @return string
     */
    public static function getIdStr($id_str)
    {
        if (empty($id_str))
            return;
        $id_str = trim(str_replace("，", ',', $id_str), ',');
        $id_ary = @explode(',', $id_str);
        if (!empty($id_ary)) {
            foreach ($id_ary as &$id) {
                $id = (int) $id;
            }
        }

        return !empty($id_ary) ? implode(',', $id_ary) : '';
    }

    /**
     * 文本入库前的过滤工作
     * @param      $textString
     * @param bool $htmlspecialchars
     *
     * @return string
     */
    public static function getSafeText($textString, $htmlspecialchars = true)
    {
        return $htmlspecialchars ? htmlspecialchars(trim(strip_tags(self::qj2bj($textString)))) : trim(strip_tags(self::qj2bj($textString)))
            ;
    }

    /**
     * XML转换
     * @param $string
     *
     * @return mixed|string
     */
    public static function getSafeXml($string)
    {
        return self::getSafeUtf8(self::getSafeText($string), $_htmlspecialchars = true);
    }

    /**
     * UTF8转换
     * @param $content
     *
     * @return mixed|string
     */
    public static function getSafeUtf8($content)
    {
        $content = mb_convert_encoding($content, 'gbk', 'utf-8');
        $content = mb_convert_encoding($content, 'utf-8', 'gbk');
        $content = preg_replace('/[\x00-\x08\x0b\x0c\x0e-\x1f]/', '', $content);
        return $content;
    }

    /**
     * 国标转换
     * @param $content
     *
     * @return mixed|string
     */
    public static function getSafeGbk($content)
    {
        $content = mb_convert_encoding($content, 'utf-8', 'gbk');
        $content = preg_replace('/[\x00-\x08\x0b\x0c\x0e-\x1f]/', '', $content);
        return $content;
    }

    //加密 cookie
    public static function docode($string, $operation = 'de', $key = '', $expiry = 0, $ckey_length = 10)
    {
        $result = null;
        //$ckey_length = 10;//随机密钥
        $key    = md5($key ? $key : FDKEY); //取得密钥MD5码
        $keya   = md5(substr($key, 0, 16)); //密钥MD5的前16位
        $keyb   = md5(substr($key, 16, 16)); //密钥MD5的后16位

        $keyc       = $ckey_length ? ($operation == 'de' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
        $cryptkey   = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);

        $string        = $operation == 'de' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
        $string_length = strlen($string);

        $box    = range(0, 255);
        $rndkey = array();
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }
        for ($j = $i = 0; $i < 256; $i++) {
            $j       = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp     = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }

        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a       = ($a + 1) % 256;
            $j       = ($j + $box[$a]) % 256;
            $tmp     = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            $result  .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }

        if ($operation == 'de') {
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            return $keyc . str_replace('=', '', base64_encode($result));
        }
    }

    /**
     * 获取10阶的hash
     * @param $pBloggerID
     *
     * @return int
     */
    public static  function hashDBID($pBloggerID)
    {
        return floor($pBloggerID / 10) % 10;
    }

    /**
     * 取模
     * @param $pBloggerID
     *
     * @return int
     */
    public static function hashTBLID($pBloggerID)
    {
        return $pBloggerID % 10;
    }
    /**
     * 全角转半角
     * @param $string
     *
     * @return string
     */
    public static function qj2bj($string)
    {
        $convert_table = Array(
            '０' => '0',
            '１' => '1',
            '２' => '2',
            '３' => '3',
            '４' => '4',
            '５' => '5',
            '６' => '6',
            '７' => '7',
            '８' => '8',
            '９' => '9',
            'Ａ' => 'A',
            'Ｂ' => 'B',
            'Ｃ' => 'C',
            'Ｄ' => 'D',
            'Ｅ' => 'E',
            'Ｆ' => 'F',
            'Ｇ' => 'G',
            'Ｈ' => 'H',
            'Ｉ' => 'I',
            'Ｊ' => 'J',
            'Ｋ' => 'K',
            'Ｌ' => 'L',
            'Ｍ' => 'M',
            'Ｎ' => 'N',
            'Ｏ' => 'O',
            'Ｐ' => 'P',
            'Ｑ' => 'Q',
            'Ｒ' => 'R',
            'Ｓ' => 'S',
            'Ｔ' => 'T',
            'Ｕ' => 'U',
            'Ｖ' => 'V',
            'Ｗ' => 'W',
            'Ｘ' => 'X',
            'Ｙ' => 'Y',
            'Ｚ' => 'Z',
            'ａ' => 'a',
            'ｂ' => 'b',
            'ｃ' => 'c',
            'ｄ' => 'd',
            'ｅ' => 'e',
            'ｆ' => 'f',
            'ｇ' => 'g',
            'ｈ' => 'h',
            'ｉ' => 'i',
            'ｊ' => 'j',
            'ｋ' => 'k',
            'ｌ' => 'l',
            'ｍ' => 'm',
            'ｎ' => 'n',
            'ｏ' => 'o',
            'ｐ' => 'p',
            'ｑ' => 'q',
            'ｒ' => 'r',
            'ｓ' => 's',
            'ｔ' => 't',
            'ｕ' => 'u',
            'ｖ' => 'v',
            'ｗ' => 'w',
            'ｘ' => 'x',
            'ｙ' => 'y',
            'ｚ' => 'z',
            '　' => ' ',
            '：' => ':',
            '。' => '.',
            '？' => '?',
            '，' => ',',
            '／' => '/',
            '；' => ';',
            '［' => '[',
            '］' => ']',
            '｜' => '|',
            '＃' => '#',
        );
        return strtr($string, $convert_table);
    }

    /**
     * 字符串截取
     * @param string $str
     * @param int $strlen
     * @param int $other
     * @return string
     */
    public static function doStrOut($str, $strlen = 10, $other = 0)
    {
        if (empty($str)) {
            return $str;
        }
        $str = @iconv('UTF-8', 'GBK', $str);
        $j   = 0;
        for ($i = 0; $i < $strlen; $i++) {
            if (ord(substr($str, $i, 1)) > 0xa0) {
                $j++;
            }
        }
        if ($j % 2 != 0) {
            $strlen++;
        }
        $rstr = @substr($str, 0, $strlen);
        $rstr = @iconv('GBK', 'UTF-8', $rstr);
        if (strlen($str) > $strlen && $other) {
            $rstr .= '...';
        }
        return $rstr;
    }

    /**
     * 字符串截取
     * Enter description here ...
     * @param string $Str  为截取字符串
     * @param int $Length  需要截取的长度
     * @param string $dot  后缀
     * @return  string
     */
    public static function doSubstr($str, $len, $dot = '...')
    {
        // 检查长度
        if (mb_strwidth($str, 'UTF-8') <= $len) {
            return $str;
        }
        // 截取
        $i    = 0;
        $tlen = 0;
        $tstr = '';
        while ($tlen < $len) {
            $chr    = mb_substr($str, $i, 1, 'utf8');
            $chrLen = ord($chr) > 127 ? 2 : 1;

            if ($tlen + $chrLen > $len)
                break;

            $tstr .= $chr;
            $tlen += $chrLen;
            $i ++;
        }
        if ($tstr != $str) {
            $tstr .= $dot;
        }

        return $tstr;
    }


    /**
     * 过滤特殊字符
     * @return mixed|string
     */
    public static function replaceHtmlAndJs($string)
    {
        if (get_magic_quotes_gpc()) {
            $string = stripslashes($string);
        }
        $string = mb_ereg_replace('^(　| )+', '', $string);
        $string = mb_ereg_replace('(　| )+$', '', $string);
        $string = mb_ereg_replace('　　', "\n　　", $string);
        //       $string    =   preg_replace('/select|insert|and|or|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file/i','',$string);
        $string = htmlspecialchars($string, ENT_QUOTES);
        return $string;
    }

    /**
     * 检测是否在设定的两个数之间
     * 结果总是出现在边界
     * 例如:
     * domid(985,0,100)=100 无边界设置
     * domid(985,0,100,20,96)=96 大边界
     * domid(0,0,100,20,96)=20 小边界
     *
     * @param int $it     一个整数
     * @param int $min    边界,较小的数
     * @param int $max    边界,较大的数
     * @param int $min_de 小边界的默认数值
     * @param int $max_de 大边界的默认数值
     * @return int
     */
    public static function doMid($it, $min, $max, $min_de = null)
    {
        $it = (int) $it;
        if (null !== $min_de && $it == 0) {
            $it = $min_de;
        } else {
            $it = max($it, $min);
            $it = min($it, $max);
        }
        return $it;
    }

    /**
     * MySQL 设为 utf8 字符集情况下不支持 emoji，评论入库后为空。
     */
    public static function cleanEmoji($text)
    {
        $clean_text     = "";
        // 删掉表情
        $regexEmoticons = '/[\x{1F600}-\x{1F64F}]/u';
        $clean_text     = preg_replace($regexEmoticons, '', $text);
        // 删掉其他符号类
        $regexSymbols   = '/[\x{1F300}-\x{1F5FF}]/u';
        $clean_text     = preg_replace($regexSymbols, '', $clean_text);
        // 删掉地图类符号
        $regexTransport = '/[\x{1F680}-\x{1F6FF}]/u';
        $clean_text     = preg_replace($regexTransport, '', $clean_text);
        $clean_text     = str_replace('سمَـَّوُوُحخ ̷̴̐خ ̷̴̐خ ̷̴̐خ امارتيخ ̷̴̐خ', '', $clean_text); //处理阿拉伯文会让iOS/MacOS崩溃
        return $clean_text;
    }

    public static function doSetId($id)
    {
        if (!empty($id)) {
            $id = preg_replace(array('/[^\d,]/', '/[,]{2,}/'), array('', ','), $id);
            $id = trim($id, ',');
            !$id && $id = 0;
        } else {
            $id = 0;
        }
        return $id;
    }
    /**
     * 解析json串
     * @param type $json_str
     * @return type
     */
    public static  function isJson($json_str)
    {
        $json_str   = str_replace('＼＼', '', $json_str);
        json_decode($json_str,true);
        return (json_last_error() == JSON_ERROR_NONE)?true:false;
    }

    /**
     * 全角转半角
     * @param string $str
     * @return mixed
     */
    public static function SBC_DBC($str = '')
    {
        if( !$str ){
            return $str;
        }
        //全角字符
        $DBC = Array(
            '０', '１', '２', '３', '４',
            '５', '６', '７', '８', '９',
            'Ａ', 'Ｂ', 'Ｃ', 'Ｄ', 'Ｅ',
            'Ｆ', 'Ｇ', 'Ｈ', 'Ｉ', 'Ｊ',
            'Ｋ', 'Ｌ', 'Ｍ', 'Ｎ', 'Ｏ',
            'Ｐ', 'Ｑ', 'Ｒ', 'Ｓ', 'Ｔ',
            'Ｕ', 'Ｖ', 'Ｗ', 'Ｘ', 'Ｙ',
            'Ｚ', 'ａ', 'ｂ', 'ｃ', 'ｄ',
            'ｅ', 'ｆ', 'ｇ', 'ｈ', 'ｉ',
            'ｊ', 'ｋ', 'ｌ', 'ｍ', 'ｎ',
            'ｏ', 'ｐ', 'ｑ', 'ｒ', 'ｓ',
            'ｔ', 'ｕ', 'ｖ', 'ｗ', 'ｘ',
            'ｙ', 'ｚ', '～', '！', '＠',
            '＃', '＄', '％', '＾', '＆',
            '＊', '（', '）', '－', '＿',
            '＋', '＝', '［', '｛', '｝',
            '］', '：', '；', '＇', '＂',
            '，', '＜', '＞', '．', '？',
            '／', '｜', '＼', '　'
        );
        //半角字符
        $SBC = Array(
            '0', '1', '2', '3', '4',
            '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'D', 'E',
            'F', 'G', 'H', 'I', 'J',
            'K', 'L', 'M', 'N', 'O',
            'P', 'Q', 'R', 'S', 'T',
            'U', 'V', 'W', 'X', 'Y',
            'Z', 'a', 'b', 'c', 'd',
            'e', 'f', 'g', 'h', 'i',
            'j', 'k', 'l', 'm', 'n',
            'o', 'p', 'q', 'r', 's',
            't', 'u', 'v', 'w', 'x',
            'y', 'z', '~', '!', '@',
            '#', '$', '%', '^', '&',
            '*', '(', ')', '-', '_',
            '+', '=', '[', '{', '}',
            ']', ':', ';', '\'', '"',
            ',', '<', '>', '.', '?',
            '/', '|', '\\', ' '
        );
        return str_replace($DBC, $SBC, $str);
    }

    /**
     * 返回正确的json中
     *
     * @param array $array
     * @return string
     */
    public static function getJson($array)
    {
        if (empty($array)) {
            return array();
        }
        if (is_array($array)) {
            self::arrayRecursive($array, 'urlencode', true);
        } else {
            $array = urlencode($array);
        }

        $json = json_encode($array,JSON_UNESCAPED_UNICODE);
        return urldecode($json);
    }
    /**
     * json串处理
     *
     * @param array $array
     * @param string $function
     * @param string $apply_to_keys_also
     * @return mixed | string
     */
    private static function arrayRecursive(&$array, $function, $apply_to_keys_also = false)
    {
        static $recursive_counter = 0;
        if (++$recursive_counter > 1000) {
            echo('possible deep recursion attack');
            return;
        }
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                self::arrayRecursive($array[$key], $function, $apply_to_keys_also);
            } else {
                $array[$key] = $function($value);
            }
            if ($apply_to_keys_also && is_string($key)) {
                $new_key = $function($key);
                if ($new_key != $key) {
                    $array[$new_key] = $array[$key];
                    unset($array[$key]);
                }
            }
        }
        $recursive_counter--;
    }

}